#pragma once
#include "debug_constants.h"
#include <stdio.h>	//printf?
#include <SDL.h>
#include <assert.h>

const Uint16 KEY_COUNT = 10;
enum KeyMask
{
	KEY_UP = 1<<0,
	KEY_DOWN = 1 << 1,
	KEY_LEFT= 1 << 2,
	KEY_RIGHT= 1 << 3,
	KEY_EXIT= 1 << 4,
	KEY_ENTER= 1 << 5,
	KEY_SPACE= 1 << 6,
	KEY_MOUSE_LEFT= 1 << 7,
	KEY_MOUSE_RIGHT= 1 << 8,
	KEY_MOUSE_MIDDLE= 1 << 9
};

/*
const Uint16 KEY_TO_SDL_COUNT = 7;
const int KeyToSDL[KEY_TO_SDL_COUNT]=
{
	SDLK_UP,
	SDLK_DOWN,
	SDLK_LEFT,
	SDLK_RIGHT,
	SDLK_ESCAPE,
	SDLK_RETURN,
	SDLK_SPACE
};

const Uint16 MOUSE_KEY_TO_SDL_COUNT = 3;
enum MouseKeyToSDL
{
	MOUSE_KEY_TO_MOUSE_LEFT= SDL_BUTTON_LEFT,
	MOUSE_KEY_TO_MOUSE_RIGHT= SDL_BUTTON_RIGHT,
	MOUSE_KEY_TO_MOUSE_MIDDLE= SDL_BUTTON_MIDDLE
};

//001000 -> 3
int _Input__MaskToIndex(int mask)
{
	if (!mask){return 0;}	//put assert here!! no mask found
	int index = 0;
	while(mask > 1)
	{
		mask >> 1;
		++index;
	}
	return index;
}
*/

struct UserInputData
{
	Uint32 down_flags;
	Uint32 pressed_flags;
	Uint32 released_flags;
};

enum KeyState
{
	KEY_STATE_DOWN,
	KEY_STATE_PRESSED,
	KEY_STATE_RELEASED
};

bool Input__IsKey(UserInputData input,KeyMask isKey,  KeyState state)
{
	switch(state)
	{
	case KEY_STATE_DOWN:
		{
			return (input.down_flags & isKey);
		}break;
	case KEY_STATE_PRESSED:
		{
			return (input.pressed_flags & isKey);
		}break;
	case KEY_STATE_RELEASED:
		{
			return (input.released_flags & isKey);
		}break;
	}
	return false;
}



#define _INPUT__SET_KEY(int_var,int_shift){(int_var) |= (int_shift);}
#define _INPUT__CLEAR_KEY(int_var, int_shift){(int_var) &= (~(int_shift));}

bool _Input_TestCases()
{
	bool Result = true;
	int val =1;			//0001
	int mask = 1<<3;	//1000 = 8
	_INPUT__SET_KEY(val,mask);	//1001 = 9
	if (val != 9)
	{
		Result = false;
	}
	mask = 1;
	_INPUT__CLEAR_KEY(val,mask); //1000 = 8
	if (val != 8)
	{
		Result = false;
	}
	mask = 1<<3;
	_INPUT__CLEAR_KEY(val,mask);//0000 = 0
	if (val != 0)
	{
		Result = false;
	}

	UserInputData state = {};
	
	_INPUT__SET_KEY(state.down_flags,KEY_SPACE);
	if (!Input__IsKey(state,KEY_SPACE,KEY_STATE_DOWN))
	{
		Result = false;
	}

	return Result;
}

void Input__GetSpace()
{
	SDL_Event event;
	while(SDL_PollEvent(&event))
	{
		printf("%d event\n",event.type);
		if(event.type == SDL_KEYDOWN)
		{

			printf("key down\n");
		}
	}
}

UserInputData Input__GetInputState(SDL_Event * event, UserInputData last_state)
{
#if DEBUG
	bool passed_tests = _Input_TestCases();
	assert(passed_tests);
#endif
	UserInputData Result = last_state;
	Result.pressed_flags = 0;
	Result.released_flags = 0;
	while(SDL_PollEvent(event))
	{
		Uint32 event_type = event->type;
		switch(event_type)
		{
		case SDL_QUIT:
			{
				_INPUT__SET_KEY(Result.down_flags,KEY_EXIT);
				_INPUT__SET_KEY(Result.pressed_flags,KEY_EXIT);
			}break;
		case SDL_KEYDOWN:
			{
				switch(event->key.keysym.sym)
				{
				case SDLK_LEFT:	{
						_INPUT__SET_KEY(Result.down_flags,KEY_LEFT);
						_INPUT__SET_KEY(Result.pressed_flags,KEY_LEFT);	}break;
				case SDLK_RIGHT:{
						_INPUT__SET_KEY(Result.down_flags,KEY_RIGHT);
						_INPUT__SET_KEY(Result.pressed_flags,KEY_RIGHT);}break;
				case SDLK_UP:{
						_INPUT__SET_KEY(Result.down_flags,KEY_UP);
						_INPUT__SET_KEY(Result.pressed_flags,KEY_UP);}break;
				case SDLK_DOWN:{
						_INPUT__SET_KEY(Result.down_flags,KEY_DOWN);
						_INPUT__SET_KEY(Result.pressed_flags,KEY_DOWN);}break;
				case SDLK_SPACE:{
					//printf("sdlk_space_down");
						_INPUT__SET_KEY(Result.down_flags,KEY_SPACE);
						_INPUT__SET_KEY(Result.pressed_flags,KEY_SPACE);}break;
				case SDLK_RETURN:{
						_INPUT__SET_KEY(Result.down_flags,KEY_ENTER);
						_INPUT__SET_KEY(Result.pressed_flags,KEY_ENTER);}break;
				case SDLK_ESCAPE:{
						_INPUT__SET_KEY(Result.down_flags,KEY_EXIT);
						_INPUT__SET_KEY(Result.pressed_flags,KEY_EXIT);	}break;
				}
			}break;
		case SDL_KEYUP:
			{
				switch(event->key.keysym.sym)
				{
				case SDLK_LEFT:	{
						_INPUT__CLEAR_KEY(Result.down_flags,KEY_LEFT);
						_INPUT__SET_KEY(Result.released_flags,KEY_LEFT);}break;
				case SDLK_RIGHT:{
						_INPUT__CLEAR_KEY(Result.down_flags,KEY_RIGHT);
						_INPUT__SET_KEY(Result.released_flags,KEY_RIGHT);}break;
				case SDLK_UP:{
						_INPUT__CLEAR_KEY(Result.down_flags,KEY_UP);
						_INPUT__SET_KEY(Result.released_flags,KEY_UP);}break;
				case SDLK_DOWN:{
						_INPUT__CLEAR_KEY(Result.down_flags,KEY_DOWN);
						_INPUT__SET_KEY(Result.released_flags,KEY_DOWN);}break;
				case SDLK_SPACE:{
					//printf("sdlk_space_up");
						_INPUT__CLEAR_KEY(Result.down_flags,KEY_SPACE);
						_INPUT__SET_KEY(Result.released_flags,KEY_SPACE);}break;
				case SDLK_RETURN:{
						_INPUT__CLEAR_KEY(Result.down_flags,KEY_ENTER);
						_INPUT__SET_KEY(Result.released_flags,KEY_ENTER);}break;
				case SDLK_ESCAPE:{
						_INPUT__CLEAR_KEY(Result.down_flags,KEY_EXIT);
						_INPUT__SET_KEY(Result.released_flags,KEY_EXIT);}break;
				}
			}break;
		case SDL_MOUSEBUTTONDOWN:
			{
				switch(event->key.keysym.sym)
				{
				case SDL_BUTTON_LEFT:{
						_INPUT__SET_KEY(Result.down_flags,KEY_MOUSE_LEFT);
						_INPUT__SET_KEY(Result.pressed_flags,KEY_MOUSE_LEFT);}break;
				case SDL_BUTTON_RIGHT:{
						_INPUT__SET_KEY(Result.down_flags,KEY_MOUSE_RIGHT);
						_INPUT__SET_KEY(Result.pressed_flags,KEY_MOUSE_RIGHT);}break;
				case SDL_BUTTON_MIDDLE:{
						_INPUT__SET_KEY(Result.down_flags,KEY_MOUSE_MIDDLE);
						_INPUT__SET_KEY(Result.pressed_flags,KEY_MOUSE_MIDDLE);}break;
				}
			}break;
		case SDL_MOUSEBUTTONUP:
			{
				switch(event->key.keysym.sym)
				{
				case SDL_BUTTON_LEFT:{
						_INPUT__CLEAR_KEY(Result.down_flags,KEY_MOUSE_LEFT);
						_INPUT__SET_KEY(Result.released_flags,KEY_MOUSE_LEFT);}break;
				case SDL_BUTTON_RIGHT:{
						_INPUT__CLEAR_KEY(Result.down_flags,KEY_MOUSE_RIGHT);
						_INPUT__SET_KEY(Result.released_flags,KEY_MOUSE_RIGHT);}break;
				case SDL_BUTTON_MIDDLE:{
						_INPUT__CLEAR_KEY(Result.down_flags,KEY_MOUSE_MIDDLE);
						_INPUT__SET_KEY(Result.released_flags,KEY_MOUSE_MIDDLE);}break;
				}
			}break;
		}
	}
	return Result;	
}